﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocketSharp;
using WebSocketSharp.Server;
using Newtonsoft.Json;
using FightLand_Sever.Model.Net;
using FightLand_Sever.Room;

namespace FightLand_Sever.Hall
{
    class HallChat : WebSocketBehavior
    {
        /// <summary>
        /// 收到大厅操作指令时触发
        /// </summary>
        public event Action<HallChat, NetInfoBase> OnHallOrder;

        /// <summary>
        /// 玩家成功连接时触发
        /// </summary>
        public event Action<HallChat> OnConnect;

        /// <summary>
        /// 玩家断开连接时触发
        /// </summary>
        public event Action<HallChat> OnDisConnect;

        /// <summary>
        /// 玩家IP地址
        /// </summary>
        public string IP { get { return this.Context.UserEndPoint.Address.ToString(); } }

        /// <summary>
        /// 绑定的玩家
        /// </summary>
        public Player BindPlayer { get; private set; }

        /// <summary>
        /// 标识连接是否正常打开
        /// </summary>
        public bool IsConnect { get { return base.Context.WebSocket.ReadyState == WebSocketState.Open; } }

        public HallChat()
        {

        }

        /// <summary>
        /// 发送数据到客户端
        /// </summary>
        /// <param name="data"></param>
        /// <param name="type"></param>
        public void SendData(string data, HallOrderType type, string tag = "")
        {
            if (this.Context.WebSocket.ReadyState == WebSocketState.Open)
            {
                var bas = new NetInfoBase((int)type, data, tag);
                string json = JsonConvert.SerializeObject(bas);
                base.Send(json);
            }
        }

        /// <summary>
        /// 关闭与玩家的连接
        /// </summary>
        public void Close()
        {
            this.Context.WebSocket.Dispose();
        }

        /// <summary>
        /// 发送大厅数据
        /// </summary>
        /// <param name="np"></param>
        /// <param name="isflogin"></param>
        private void SendHallData(NetPlayer np, bool isflogin)
        {
            var obj = new
            {
                Player = np, //玩家信息
                IsFirstLogin = isflogin //指示该玩家是否为第一次登陆
            };
            var json = JsonConvert.SerializeObject(obj);
            this.SendData(json, HallOrderType.返回大厅数据);
        }

        protected override async Task OnMessage(MessageEventArgs e)
        {
            using (var rs = new System.IO.StreamReader(e.Data))
            {
                string json = rs.ReadToEnd();
                NetInfoBase bas = JsonConvert.DeserializeObject<NetInfoBase>(json);
                Player ply = this.BindPlayer;
                json = bas.JsonData;
                if (bas != null && this.OnHallOrder != null)
                {
                    this.OnHallOrder(this, bas);
                }
                //try
                //{
                switch ((HallOrderType)bas.OrderType)
                {
                    case HallOrderType.请求大厅数据:
                        {
                            string pid = bas.Tag;
                            Player py = null;
                            //检测玩家id是否在线
                            if (Management.HasPlayerInOnlineByID(pid))
                            {
                                py = Management.GetOnlinePlayerByID(pid);
                                py.HallData.SetWebSock(this);
                            }
#if !DEBUG
                            //如果id没有匹配说明有可能以新的浏览器打开,为了保证一台电脑只能连接一次,所以在此检测IP是否已经存在
                            if (py == null && Management.HasPlayerInOnlineByIP(IP))
                            {
                                py = Management.GetOnlinePlayerByIP(IP);
                                py.HallData.SetWebSock(this);
                            }

                             //如果玩家IP也未找到则说明玩家已经下线,所以去本地数据对象中寻找玩家
                            if (py == null)
                            {
                                var np = Management.GetPlayerDataInAll(IP);
                                //存在该玩家数据则拿到该数据,否则生成新玩家
                                if (np != null)
                                {
                                    py = new Player(np, true);
                                    Management.AddToOnline(py);
                                }
                            }
#endif
                            if (py == null)
                            {
                                py = new Player();
                                py.HallData.SetWebSock(this);
                                Management.AddToOnline(py);
                            }
                            Log.Print("玩家" + this.IP + "已连接到服务器,玩家ID:" + py.PlayerID);
                            this.BindPlayer = py;
                            this.SendHallData(new NetPlayer(py), false);
                            break;
                        }
                    case HallOrderType.进入匹配队列:
                        {
                            MatchingQueue.Enqueue(ply);
                            break;
                        }
                    case HallOrderType.退出匹配队列:
                        {
                            Log.Print("玩家" + this.BindPlayer.Name + "退出了匹配队列");
                            MatchingQueue.Remove(ply.PlayerID);
                            break;
                        }
                    case HallOrderType.更新玩家信息:
                        {
                            var info = JsonConvert.DeserializeAnonymousType(json, new
                            {
                                name = "",
                                roleid = 1,
                                headid = 1,
                                gender = 0,
                            });
                            Management.UpdatePlayer(ply.PlayerID, info.headid, info.roleid, info.gender, info.name);
                            break;
                        }
                    case HallOrderType.创建房间:
                        {
                            var rom = JsonConvert.DeserializeAnonymousType(json, new { pwd = "", bts = 0 });
                            GameRoom room = new GameRoom(ply, rom.bts, RoomModel.Room, rom.pwd);
                            ply.RoomData.RoomWhich = room;
                            Management.AddRoom(room);
                            this.SendData(JsonConvert.SerializeObject(new { pid = BindPlayer.PlayerID, roomid = room.RoomID, roompwd = room.RoomPwd }), HallOrderType.房间创建完毕);
                            break;
                        }
                    case HallOrderType.请求房间列表:
                        {
                            //获取房间信息
                            var roms = Management.GetRooms().Where(r => r.RoomModel == RoomModel.Room).Select(r =>
                                {
                                    return new NetRoom()
                                    {
                                        RoomID = r.RoomID.ToString(),
                                        BtScore = r.BtScore,
                                        MasterName = r.RoomMaster.Name,
                                        MasterHead = r.RoomMaster.HeadID,
                                        NowCount = r.MemberCount,
                                        IsLock = !string.IsNullOrEmpty(r.RoomPwd)
                                    };
                                }).ToArray();
                            var romjson = JsonConvert.SerializeObject(roms);
                            ply.HallData.SendData(romjson, HallOrderType.推送房间列表);
                            break;
                        }
                    case HallOrderType.请求排名信息:
                        {
                            //获取排名信息
                            var rks = Management.GetAllPlayers().OrderBy(r => long.Parse(r.Mark)).ToArray();
                            var rkjson = JsonConvert.SerializeObject(rks);
                            ply.HallData.SendData(rkjson, HallOrderType.推送排名信息);
                            break;
                        }
                    case HallOrderType.请求进入房间:
                        {
                            var obj = JsonConvert.DeserializeAnonymousType(json, new { roomid = "", pwd = "" });
                            if (Management.HasRoom(obj.roomid))
                            {
                                var rom = Management.GetRoom(obj.roomid);
                                if (rom.MemberCount >= 3)
                                {
                                    this.BindPlayer.HallData.SendData("", HallOrderType.拒绝进入房间, "房间成员已满!");
                                    return;
                                }
                                if (rom.RoomPwd != obj.pwd)
                                {
                                    this.BindPlayer.HallData.SendData("", HallOrderType.拒绝进入房间, "房间密码错误!");
                                    return;
                                }
                                this.BindPlayer.HallData.SendData(JsonConvert.SerializeObject(new
                                {
                                    roomid = rom.RoomID,
                                    pwd = rom.RoomPwd
                                }), HallOrderType.允许进入房间);
                            }
                            else
                            {
                                this.BindPlayer.HallData.SendData("", HallOrderType.拒绝进入房间, "房间已销毁!");
                            }
                            break;
                        }
                    case HallOrderType.发送广播消息:
                        {
                            BindPlayer.Mark -= 8888;
                            Management.SendBarrage(BindPlayer.Name, bas.Tag, false);
                            break;
                        }
                }
                //}
                //catch (Exception ex)
                //{
                //    Log.Print(string.Format("异常信息:{0} \n" +
                //"异常方法:{1}\n" +
                //"堆栈信息:{2}\n", ex.Message, ex.TargetSite, ex.StackTrace), ConsoleColor.Red);
                //}
            }
        }

        protected override async Task OnClose(CloseEventArgs e)
        {
            if (this.OnDisConnect != null) this.OnDisConnect(this);
        }

        protected override async Task OnError(ErrorEventArgs e)
        {
            Log.Print(string.Format("异常信息:{0} \n" +
                "异常方法:{1}\n" +
                "堆栈信息:{2}\n", e.Exception.Message, e.Exception.TargetSite, e.Exception.StackTrace), ConsoleColor.Red);
        }

        protected override async Task OnOpen()
        {
            if (this.OnConnect != null) this.OnConnect(this);
        }
    }
}
